Skip to content

refactor filesystem context management and discovery#943

Closed
ZCShou wants to merge 16 commits into
devfrom
fs2
Closed

refactor filesystem context management and discovery#943
ZCShou wants to merge 16 commits into
devfrom
fs2

Conversation

@ZCShou

@ZCShou ZCShou commented May 26, 2026

Copy link
Copy Markdown
Contributor

文件系统栈重构 PR 说明

1. 背景与问题

对于整个 fs,旧的实现以 axfs::fops 和若干分散的 helper 为核心,能支撑基本 std::fs 场景,但整体仍停留在较扁平的文件操作封装阶段:VFS 节点模型、mount tree、rootfs 发现、分区扫描、文件缓存、POSIX 元数据和上层 API 语义之间边界不够清晰。随着 StarryOS、Axvisor、ArceOS std、动态 rootfs 和多文件系统格式同时推进,旧结构已经很难继续扩展。

第一,VFS 抽象过薄。dev 上的 axfs_vfs 主要围绕旧的 VfsNodeOps / VfsDirEntry / VfsNodeRef 工作,目录、文件、元数据、路径解析和 mount 关系没有形成稳定的对象模型。上层依赖 fops 做大量包装,导致 rename、mount、stat、symlink、directory fd 等语义需要在不同层重复处理。

第二,mount tree 能力不足。旧代码有 mounts.rs,但没有完整的 Mountpoint / Location 模型,也缺少 per-location 的 mountpoint children、readonly、propagation、pivot/move/bind 这类可组合状态。StarryOS 需要更接近 Linux 的 mount 行为时,旧模型只能继续堆逻辑,难以表达“同一个 DirEntry 在不同 mountpoint 下的位置”和“mount root / parent location”的关系。

第三,rootfs 初始化逻辑集中且难复用。dev 里 rootfs 相关逻辑分散在 root.rspartition.rsdev.rs 等文件中,block device、分区扫描、filesystem 构造、root 选择和 mount 初始化耦合在一起。对于 runtime 自动启动这是可用的,但对于测试、Starry、Axvisor 或已经构造好 Filesystem 的调用方来说,不能直接复用“初始化 root filesystem context”这一步。

第四,block device 与 partition region 抽象不够统一。旧代码分别处理 FAT/ext4 device、partition reader 和 root 选择,没有把“共享物理设备”和“某个 filesystem 可见的 LBA region”提升成公共 API。后续要暴露 discovered filesystems、挂载非 root 分区或复用同一个物理 block device 时,会遇到重复包装和所有权传递问题。

第五,高层 file API 和底层 filesystem 适配耦合。旧 fops.rs 同时承担 FileDirectoryOpenOptions、metadata 映射和一部分 API 语义。它没有 page cache 层,也没有更明确的 FileBackend 区分。普通文件、目录、设备文件、socket/fifo、O_PATH、O_APPEND 等语义容易互相影响。

第六,POSIX / ArceOS API 语义不够稳定。旧实现对 stat、getdents、directory fd、默认目录权限、feature 暴露等行为没有统一地落在新的 highlevel/VFS 模型上。迁移过程中如果只做结构替换,很容易出现 inode/uid/gid/blksize 被硬编码、目录 fd 失去真实 location、getdents 部分读取语义丢失等兼容性回退。

第七,底层文件系统适配较粗。dev 上 FAT 和 ext4 适配以 fatfs.rsext4fs.rs 这类大文件为主,不利于把 disk、file、dir、fs、util 分开测试和维护。ext4 也没有同时保留 rsext4/lwext4 两种后端的清晰模块边界。

因此,本 PR 进行了一次文件系统栈重构:用新的 VFS / highlevel / discovery 架构替换旧 fops + root/partition/dev 模型,同时把迁移过程中发现的兼容性和正确性问题一并修正。

2. 核心修改

2.1 总体架构

新的文件系统栈按职责拆成以下层级:

runtime / OS policy
  |
  | init_filesystems(block_devs, bootargs)
  | init_root_filesystem(fs)
  v
axfs public API
  |
  | block.rs: FsBlockDevice / SharedBlockDevice / BlockRegion / VolumeReader
  | discovery.rs: scan volumes, parse root=, select root, expose discovered fs
  | fs/: FAT / ext4 filesystem constructors
  | highlevel/: FsContext, File, OpenOptions, ReadDir, page cache
  v
axfs_vfs
  |
  | Mountpoint / Location
  | DirEntry / FileNode / DirNode
  | path, metadata, mount propagation
  v
concrete filesystem implementations
  |
  | fatfs adapter
  | rsext4 / lwext4 adapter
  | ramfs / devfs
  v
block device driver

dev 旧代码相比,最重要的变化是:

  • 删除旧 os/arceos/modules/axfs/src/fops.rs
  • 删除旧 api/dir.rsapi/file.rsmounts.rspartition.rsroot.rsdev.rs
  • 新增 block.rsdiscovery.rs
  • 新增 highlevel/file.rshighlevel/fs.rs
  • 将 FAT / ext4 拆到 fs/fat/*fs/ext4/{rsext4,lwext4}/*
  • 将 VFS 拆成 mount.rsnode/{dir,file,mod}.rspath.rstypes.rs

新入口把“从 block devices 自动发现 rootfs”和“直接使用已构造 filesystem 初始化 root”分开:

pub fn init_filesystems(block_devs: Vec<Box<dyn FsBlockDevice>>, bootargs: Option<&str>);
pub fn init_root_filesystem(fs: Filesystem);

init_filesystems() 面向 runtime 自动启动路径,负责扫描设备、选择 root、构造 filesystem;init_root_filesystem() 面向上层已经拿到 Filesystem 的场景,直接初始化全局 FsContext。这使 Starry、Axvisor 和测试不需要被迫经过 block discovery。

2.2 ArceOS / StarryOS / Axvisor 引用路径

本 PR 不是只替换 axfs 内部实现。axfsaxfs_vfs 是 ArceOS、StarryOS、Axvisor 共同依赖的基础文件系统层,并且每个 OS 的入口不止一条。迁移时需要同时保证 runtime 初始化、std/posix API、Starry syscall、pseudofs、Axvisor shell/config/image 这些路径都落到同一套 highlevel/VFS 语义上。

ArceOS 的主要引用路径如下:

ArceOS runtime rootfs 初始化路径
  os/arceos/modules/axruntime/src/lib.rs
    -> ax_fs::init_filesystems(block_devs, bootargs)
  os/arceos/modules/axruntime/src/devices.rs
    -> impl ax_fs::FsBlockDevice for ax_driver::block::Block wrapper
  os/arceos/modules/axfs/src/discovery.rs
    -> scan block devices / select root / construct filesystem
  os/arceos/modules/axfs/src/lib.rs
    -> init_root_filesystem(fs)
  os/arceos/modules/axfs/src/highlevel/fs.rs
    -> ROOT_FS_CONTEXT / task-local FS_CONTEXT

这条路径负责系统启动时从 virtio-blk、ramdisk 或平台 block device 中发现 rootfs。相关 feature 在 os/arceos/modules/axruntime/Cargo.tomlos/arceos/api/axfeat/Cargo.toml 中传播:fs 打开 runtime block 初始化,fs-fat / fs-ext4 同时打开 ax-fs 和 runtime 侧格式支持。

ArceOS Rust std / axstd 路径
  os/arceos/ulib/axstd/src/fs/{mod.rs,file.rs,dir.rs}
    -> ax_api::fs
  os/arceos/ulib/axstd/src/env.rs
    -> ax_api::fs::{ax_current_dir, ax_set_current_dir}
  os/arceos/ulib/arceos-rust/lib/src/interface/fs.rs
    -> ax_api::fs::{ax_create_dir, ax_remove_file, ax_remove_dir, ...}
  os/arceos/api/arceos_api/src/imp/fs.rs
    -> ax_fs::{File, OpenOptions, ReadDir, FS_CONTEXT}
  os/arceos/modules/axfs/src/highlevel/*
    -> axfs_vfs::{Location, Metadata, NodeType, Mountpoint}

这条路径对应 std::fs / axstd::fs 风格调用,是 ArceOS examples、Axvisor 和普通 Rust 应用最常走的接口。PR 中保留 fs-api feature 暴露,就是为了让这条路径不因为内部重构而断开。

ArceOS POSIX API 路径
  os/arceos/api/arceos_posix_api/src/imp/fs.rs
    -> ax_fs::{OpenOptions, ReadDir, File, FS_CONTEXT}
    -> ax_fs_vfs::{Location, Metadata, NodeType}

这条路径服务 libc/POSIX syscall 语义,重点依赖真实 Metadata、目录 LocationReadDir::rewind()NodeType as d_type。因此本 PR 在迁移结构的同时恢复 stat/getdents/lseek(directory) 等稳定语义。

ArceOS Unix socket 文件系统路径
  os/arceos/modules/axnet-ng/src/unix/mod.rs
    -> ax_fs::{FS_CONTEXT, OpenOptions}
    -> ax_fs_vfs::NodeType

Unix domain socket bind/open 会经过 FS_CONTEXT.resolve()OpenOptions.open(),所以特殊节点、socket 类型、path resolve 的行为也必须和普通文件路径共享同一套 VFS 规则。

StarryOS 的引用路径更分散,因为 Starry 既直接使用 ax_fs,又直接构造大量 ax_fs_vfs 节点:

StarryOS 文件对象与 fd 层
  os/StarryOS/kernel/src/file/mod.rs
    -> ax_fs::{FS_CONTEXT, FileBackend, FileFlags, OpenOptions}
  os/StarryOS/kernel/src/file/fs.rs
    -> ax_fs::{File, ReadDir, FsContext, FileBackend}
    -> ax_fs_vfs::{Location, Metadata, NodeFlags}
  os/StarryOS/kernel/src/file/memfd.rs
    -> ax_fs::{FileBackend, FileFlags}

这是 Starry 内核自己的 FileLike / fd table 包装层。普通文件、目录、memfd、mmap backend 都会在这里把 ax_fs::FileFileBackend 转换成 Starry 的 fd 对象。

StarryOS syscall/fs 路径
  os/StarryOS/kernel/src/syscall/fs/fd_ops.rs
    -> ax_fs::{FS_CONTEXT, OpenOptions, OpenResult, FileBackend}
    -> ax_fs_vfs::{DirEntry, FileNode, Location, NodeOps, NodeType, Reference}
  os/StarryOS/kernel/src/syscall/fs/io.rs
    -> ax_fs::{FS_CONTEXT, FileFlags, OpenOptions}
  os/StarryOS/kernel/src/syscall/fs/ctl.rs
    -> ax_fs::{FS_CONTEXT, FsContext}
    -> ax_fs_vfs::{MetadataUpdate, NodePermission, NodeType, path::Path}
  os/StarryOS/kernel/src/syscall/fs/stat.rs
    -> ax_fs::FS_CONTEXT
    -> ax_fs_vfs::{Location, NodePermission}
  os/StarryOS/kernel/src/syscall/fs/memfd.rs
    -> ax_fs::{FS_CONTEXT, OpenOptions}

这条路径覆盖 open/openat、read/write、mkdir/rename/chdir/sync、stat/lstat/fstat、memfd 等 syscall。它依赖新的 FsContext 进行 cwd/root path resolve,也依赖 Location 保留目录 fd 的真实挂载位置。

StarryOS mount / loop block 路径
  os/StarryOS/kernel/src/pseudofs/dev/loop_block.rs
    -> impl ax_fs::FsBlockDevice for LoopBlockDevice
  os/StarryOS/kernel/src/syscall/fs/mount.rs
    -> ax_fs::{BlockRegion, FilesystemKind, new_filesystem_from_dyn_by_kind}
    -> ax_fs::{FS_CONTEXT, FsContext::propagate_pivot_root}
    -> ax_fs_vfs::Mountpoint

这条路径不是启动 rootfs discovery,而是运行时 mount 路径:Starry 可以把 loop 设备包装成 FsBlockDevice,指定 BlockRegionFilesystemKind 构造 ext4 filesystem,再挂到当前 mount tree。新的公共 FsBlockDevice / BlockRegion / Mountpoint API 主要就是为了支撑这种复用。

StarryOS 进程加载与 mmap 路径
  os/StarryOS/kernel/src/entry.rs
    -> ax_fs::FS_CONTEXT
  os/StarryOS/kernel/src/syscall/task/execve.rs
    -> ax_fs::FS_CONTEXT
  os/StarryOS/kernel/src/syscall/task/clone.rs
    -> ax_fs::FS_CONTEXT task-local clone
  os/StarryOS/kernel/src/mm/loader.rs
    -> ax_fs::{CachedFile, FS_CONTEXT, FileBackend}
    -> ax_fs_vfs::Location
  os/StarryOS/kernel/src/mm/aspace/backend/{file.rs,cow.rs}
    -> ax_fs::{CachedFile, FileBackend, FileFlags}

这条路径负责解析可执行文件、解释器、动态链接器和 file-backed mmap。它直接依赖 CachedFileFileBackend 和 task-local FS_CONTEXT,所以 page cache、append lock、dirty page 日志和 path resolve 变更都会影响 Starry 进程加载性能与正确性。

StarryOS pseudofs / devfs / procfs 路径
  os/StarryOS/kernel/src/pseudofs/mod.rs
    -> ax_fs::{FS_CONTEXT, FsContext}
    -> ax_fs_vfs::{Filesystem, DirNodeOps, FileNodeOps, WeakDirEntry}
  os/StarryOS/kernel/src/pseudofs/{fs.rs,proc.rs,sysfs.rs,tmp.rs,debug.rs}
    -> ax_fs_vfs::{Filesystem, NodeType, NodePermission, VfsResult}
  os/StarryOS/kernel/src/pseudofs/dev/*
    -> ax_fs_vfs::{NodeFlags, DeviceId, VfsResult, ...}

这条路径由 Starry 自己实现 procfs、sysfs、tmpfs、debugfs、devfs 等伪文件系统节点,再挂入全局 root。它不一定经过 axfs 的 FAT/ext4 适配,但必须和 axfs_vfsFilesystemDirEntryMountpointLocation 模型兼容。

StarryOS 其他直接 FS_CONTEXT 路径
  os/StarryOS/kernel/src/syscall/net/socket.rs
    -> ax_fs::FS_CONTEXT
    -> ax_fs_vfs::{MetadataUpdate, NodeType}
  os/StarryOS/kernel/src/syscall/sys.rs
    -> ax_fs::FS_CONTEXT

Unix socket bind、系统信息路径解析等零散入口也直接依赖 FS_CONTEXT,因此不能只验证 syscall/fs/*

Axvisor 当前主要通过 std::fs / ax_std::fs 间接使用文件系统,没有像 Starry 那样直接操作 ax_fs_vfs mount tree,但也有多条入口:

Axvisor VM config 路径
  os/axvisor/src/vmm/config.rs
    -> ax_std::fs::{read_dir, File::open}
    -> ax_std::io::{BufReader, Read}
    -> os/arceos/ulib/axstd/src/fs/*
    -> os/arceos/api/arceos_api/src/imp/fs.rs
    -> ax_fs::{FS_CONTEXT, OpenOptions, File, ReadDir}

这条路径从 /guest/vm_default 读取 VM 配置目录和 .toml 文件,依赖 read_dir()、metadata、open/read 的 std 语义。

Axvisor guest image 路径
  os/axvisor/src/vmm/images/mod.rs
    -> std::fs::File
    -> std::io::Read
    -> axstd / arceos-rust std facade
    -> ax_api::fs
    -> ax_fs highlevel file

这条路径读取 guest kernel / image 内容,主要依赖 File::open()read_exact()。因此 page cache、direct backend 和底层 FAT/ext4 read 路径都会影响 VM 镜像加载。

Axvisor shell 路径
  os/axvisor/src/shell/command/base.rs
    -> std::fs::{self, File, FileType}
    -> ls / cat / metadata / read_dir / remove 等 shell 命令
  os/axvisor/src/shell/command/vm.rs
    -> std::fs::read_to_string
    -> VM command 读取配置文本

这条路径是交互式 shell 对文件系统的引用。它走 std facade,但覆盖目录枚举、metadata、文件类型、权限 mode、读文件等更接近用户态工具的行为,所以也是验证 getdentsstatNodeType 映射的重要入口。

2.3 VFS:从节点引用模型升级为 Mountpoint / Location 模型

axfs_vfs 现在提供更明确的对象层级。

DirEntry 表示一个 filesystem 内的目录项,持有:

  • Node::FileNode::Dir
  • NodeType
  • Reference
  • user data

Location 表示某个 DirEntry 在某个 Mountpoint 下的位置。这样同一个 filesystem entry 可以在不同 mountpoint 中出现,而路径解析、absolute path、mount parent、readonly 状态都可以通过 Location 表达。

Mountpoint 表示 mount tree 上的一个挂载点,包含:

  • root DirEntry
  • parent location
  • child mountpoints
  • device id
  • readonly / expire 状态
  • propagation 状态
  • shared peers / slaves / masters

这比旧 mounts.rs 更适合表达 bind mount、move mount、pivot root、readonly propagation 等组合行为。

本 PR 同时修复了 mount propagation 的一个关键正确性问题。传播 mount 到 peers/slaves 时不再复用同一个 Arc<Mountpoint>,而是创建独立 bind replica:

let replica = Self::bind(&child.root_location(), location.clone(), true);
Self::attach_child(&target_parent, location, &replica)?;

这避免不同 peer 共享同一个 mountpoint 的 childrenlocationreadonly 等状态。

rename 后 VFS cache 也做了修正。目录 rename 后不再把旧目录 cache 直接搬到新 entry,因为旧 cache 中子 DirEntry 的 parent reference 仍指向旧路径。现在保留 user data 和 mountpoint,丢弃旧 cache,让后续 lookup 从底层 FS 重建正确 parent。

2.4 Block Device、Partition Region 与 Rootfs Discovery

block.rs 提供公共块设备接口:

pub trait FsBlockDevice: Send {
    fn name(&self) -> &str;
    fn num_blocks(&self) -> u64;
    fn block_size(&self) -> usize;
    fn read_block(&mut self, block_id: u64, buf: &mut [u8]) -> AxResult;
    fn write_block(&mut self, block_id: u64, buf: &[u8]) -> AxResult;
    fn flush(&mut self) -> AxResult;
}

SharedBlockDevice 让 discovery、root filesystem 构造和后续 discovered mount 共享同一个物理设备:

pub struct SharedBlockDevice {
    name: String,
    inner: Arc<SpinNoIrq<Box<dyn FsBlockDevice>>>,
}

BlockRegion 描述某个 filesystem 可见的 LBA 范围,RegionBlockDevice<T> 将 region 内相对 block 映射为物理 block,并做边界检查。VolumeReader 适配 rd-block-volume,用于 GPT/MBR/raw 扫描。

discovery.rs 接管旧 root.rs / partition.rs 的职责,但拆成更清晰的阶段:

  1. 收集 block devices 为 DiscoveredDisk
  2. rd-block-volume 扫描 raw/GPT/MBR volumes
  3. 检测 FAT / ext4 magic
  4. 解析 bootargs 中的 root=
  5. 生成 root candidates
  6. 根据 RootSelectionPolicy 选择 root
  7. 构造 filesystem 并调用 init_root_filesystem(fs)
  8. 保存 discovered filesystem 列表,供后续挂载非 root 分区

支持的 root 参数包括:

  • /dev/mmcblkXpY
  • /dev/sdXN
  • PARTUUID=...
  • PARTLABEL=...

默认选择策略:

pub struct RootSelectionPolicy {
    pub preferred_partlabel: Option<String>,
    pub allow_single_supported_partition: bool,
    pub allow_single_raw_device: bool,
}

默认优先唯一 rootfs label;否则允许唯一受支持分区;再否则允许唯一 raw device。这样既能支持当前 FAT raw disk 测试资产,也能支持后续 ext4/partition rootfs。

discovered disks 保存时避免了旧写法的整体 clone,只 clone 选中的 selected 并按原位置插回列表,保持枚举顺序。

2.5 High-Level FS API:替代旧 fops

fops.rs 被拆成两个 highlevel 模块:

  • highlevel/fs.rsFsContext、current dir、path resolve、read_dir、metadata、create/remove/rename
  • highlevel/file.rsOpenOptionsOpenResultFileFileBackendCachedFile

FsContext 是上层共享的路径上下文,持有 root/current directory。它替代旧 API 层直接操作全局路径字符串的方式,使 Starry/ArceOS/Axvisor 可以使用同一套 root/current dir 语义。

FileBackend 显式区分 cached 与 direct:

pub enum FileBackend {
    Cached(CachedFile),
    Direct(Location),
}

普通文件默认可走 page cache;设备、FIFO、socket、path-only handle、direct option 或 NON_CACHEABLE 节点走 direct。这样旧 fops 中混在一起的普通文件和特殊文件语义被拆开。

page cache 由 CachedFileShared 承载。同一 inode 的 cached handles 共享 page cache 和 append lock:

struct CachedFileShared {
    page_cache: Mutex<LruCache<u32, PageCache>>,
    evict_listeners: Mutex<LinkedList<EvictListenerAdapter>>,
    append_lock: RwLock<()>,
}

之前 append lock 若放在 handle 上,多次打开同一文件后会出现并发 append 覆盖:两个 handle 都读到相同 EOF,然后写入相同 offset。现在 append offset 选择在同一 inode 级别串行化。

O_PATH 入口也被补通。OpenOptions::path(true) 不再因为 read/write/append 都为 false 被拒绝:

(false, false, false) => FileFlags::empty(),

随后统一附加 FileFlags::PATH。实际 I/O 会被 File::is_path() 拒绝,但 path-only handle 可以用于保存位置、绕过部分 open-time 检查。

PageCache::Drop 对 dirty page 未刷写的情况从 warn! 提升到 error!,让真实数据丢失风险在日志和 CI 中更容易被捕获。

2.6 POSIX / ArceOS API 迁移

arceos_api 不再 re-export 旧 fops 类型,而是基于新的 ax_fs::{File, OpenOptions, ReadDir}ax_fs_vfs::Metadata 提供稳定 API。

arceos_posix_api 的文件层也迁移到新 highlevel API:

  • File 包装 ax_fs::File
  • Directory 保存真实 LocationReadDir
  • stat() 从真实 Metadata 构造
  • getdents64 写入真实 inode、offset、node type
  • file_type_to_d_type() 直接返回 NodeType as u8
  • 目录 fd 支持 lseek(fd, 0, SEEK_SET) 重置读取位置
  • getdents 遇到中途错误时,如果已有部分结果,则返回已写入字节数

ReadDir 新增:

pub fn rewind(&mut self) {
    self.buf.clear();
    self.offset = 0;
    self.ended = false;
}

这覆盖 libc rewinddir() 常见实现。

axstd feature 也做了同步:fs-api 下继续暴露 axstd::fs 和 current dir API,避免迁移后已有调用者因为 feature 切分变化而失效。

2.7 具体文件系统适配

FAT 适配从旧 fatfs.rs 拆为:

  • fs/fat/disk.rsSeekableDisk
  • fs/fat/fs.rs:filesystem object 和 root dir
  • fs/fat/file.rs:file node ops
  • fs/fat/dir.rs:directory node ops
  • fs/fat/util.rs:metadata、time、error 映射

其中 FAT 时间转换不再对非法 DOS date/time unwrap(),而是在解析失败时返回默认时间,避免坏镜像或异常元数据导致 kernel panic。

ext4 适配从旧 ext4fs.rs 拆为两套后端:

  • fs/ext4/rsext4/*
  • fs/ext4/lwext4/*

rsext4 适配层去掉了 Ext4State::split() 中不必要的 unsafe:

pub(crate) fn split(&mut self) -> (&mut rsext4::Ext4FileSystem, &mut Jbd2Dev<Ext4Disk>) {
    (&mut self.fs, &mut self.dev)
}

同时将 inodetable_cahce 修正为 inodetable_cache,减少维护噪声。

ramfs/devfs 也迁移到新的 VFS node API。ramfs 的 directory rename rebind 从递归改为显式栈,避免深目录树 rename 造成内核栈溢出。

3. 遗留问题与后续工作

3.1 Filesystem 全局锁与 IRQ Completion I/O

当前 FAT、rsext4、lwext4 适配层仍然依赖 filesystem 级别锁保护底层库状态。某些路径会在持有 filesystem state lock 时进入 block I/O。如果底层 block driver 使用 IRQ completion + wait queue,未来需要继续审视“持锁等待 I/O 完成”的锁顺序和中断上下文约束。

本 PR 没有把 filesystem 内部状态拆成细粒度锁,也没有引入异步 block I/O。当前目标是同步、有限步、RTOS 友好的 I/O 路径,而不是完整实现 Linux page cache / writeback / journal 调度模型。

3.2 Page Cache 错误传播仍然有限

dirty page drop 已经提升为 error!,但 page cache 仍没有完整 filesystem error state。理想情况下,writeback 或 eviction 失败后应能:

  • 标记文件或 filesystem 进入错误状态
  • 后续 fsync() / close() / write 返回可观测错误
  • 必要时把 filesystem remount 为 readonly

当前只是在 drop 时暴露强日志,不会完整模拟 Linux 的 address_space error accounting。

3.3 Mount Propagation 仍是简化模型

当前 propagation 已修复“多个 peer 共享同一个 mountpoint Arc”的严重问题,但仍不是完整 Linux mount namespace / propagation 实现。仍需后续验证:

  • shared/slave 组关系的生命周期管理
  • recursive bind mount 的子 mount 复制语义
  • umount propagation
  • move mount 与 propagation 组合行为

现阶段目标是保证不会发生明显的 mountpoint 状态串扰。

3.4 O_PATH 只补通入口,未实现完整 Linux 语义

O_PATH 当前能成功创建 path-only handle,并通过 File::is_path() 拒绝实际 I/O。但完整 Linux 语义还包括更多细节,例如哪些 fcntlfstatatopenat 组合允许使用 O_PATH fd。本 PR 只修复已有设计被入口封死的问题。

3.5 Root Selection 仍以当前测试资产为默认

默认 root 选择仍保留“FAT raw disk 可用”的兼容路径。虽然支持 ext4 magic、partition table、PARTUUID/PARTLABEL,但本 PR 没有切换 std 默认 rootfs 到 ext4,也没有要求测试镜像迁移。后续如果统一测试资产到 ext4,需要同步调整 arceos-rust std feature 和镜像生成逻辑。

3.6 Metadata 完整性仍依赖底层 Filesystem

POSIX stat 已从硬编码恢复为真实 Metadata,但各底层 filesystem 的 metadata 仍有不完整处。例如 FAT 没有 Unix uid/gid/permission 原生语义,inode 和 blocks 也可能是近似值。这比硬编码更好,但还不是完整 POSIX 文件系统。

3.7 StarryOS 与 axfs/axfs_vfs 仍存在部分重复实现

StarryOS 当前既直接使用 ax_fs::{File, OpenOptions, FS_CONTEXT, FileBackend},又在 kernel/src/file/*kernel/src/syscall/fs/*kernel/src/pseudofs/* 中维护自己的 fd 包装、目录包装、pseudofs/devfs/procfs 节点和部分 mount/syscall glue。这些实现和 axfs highlevel 层、axfs_devfsaxfs_ramfsaxfs_vfs 的职责存在重叠。

本 PR 的处理方式是先统一接口和语义:让 StarryOS 继续通过新的 FsContextLocationMountpointFileBackendReadDir 接入文件系统栈,避免在大重构中同时迁移所有 Starry 私有封装。后续可以继续收敛:

  • 将 Starry 通用 fd / directory wrapper 中与 ax_fs::File 重复的逻辑下沉为可复用 helper
  • 评估 Starry pseudofs/devfs 中可共享的节点实现,迁移到 axfs_devfsaxfs_ramfs 或新的公共 pseudo-fs crate
  • 将 Starry syscall 层保留为 Linux ABI 适配层,避免继续复制 VFS path resolve、metadata、mount 状态管理逻辑

3.8 rsext4 命名修正是源内 API 变更

inodetable_cahce 已改为 inodetable_cache。这是组件内部命名修复;如果外部 crate 直接访问这个 public field,可能需要同步改名。当前 workspace 内引用已经全部更新并通过 clippy。

4. 验证

针对直接影响的 crate 进行了 clippy 验证:

cargo fmt
git diff --check
cargo xtask clippy --package ax-fs-vfs
cargo xtask clippy --package ax-fs-ramfs
cargo xtask clippy --package ax-fs
cargo xtask clippy --package rsext4
cargo xtask clippy --package ax-posix-api
cargo xtask clippy --package ax-std
cargo xtask clippy --package ax-api

ZCShou added 16 commits May 25, 2026 16:30
- Introduced `fs.rs` to manage filesystem context, including root and current directory handling.
- Added functionality for resolving paths, reading, writing, and managing directories and files.
- Implemented symlink resolution with a limit on the number of symlinks followed.
- Created a registry for filesystem contexts to support task-local storage and root pivoting.
- Added `ReadDir` iterator for directory entries.
- Created `mod.rs` to organize and expose the `file` and `fs` modules.
- Updated Cargo.toml to streamline filesystem dependencies by removing redundant entries and introducing new features for ext4 and fat filesystems.
- Modified board configuration files to eliminate the "fs" feature where it was no longer necessary.
- Adjusted tests and build scripts to reflect the removal of the "fs" feature, ensuring compatibility with the new filesystem structure.
- Introduced a new `fs_policy.rs` file to manage filesystem detection and initialization, enhancing the overall organization and clarity of the filesystem handling logic.
- Added a new module `discovery.rs` to handle the discovery of filesystems on block devices.
- Introduced `RootSelectionPolicy` to define rules for selecting the root filesystem when no explicit boot arguments are provided.
- Updated `lib.rs` to include the new discovery module and its functionalities.
- Modified `Cargo.toml` to enable filesystem features by default.
- Enhanced the initialization process for filesystems to support automatic detection and selection based on the defined policy.
# Conflicts:
#	os/axvisor/configs/board/phytiumpi.toml
#	os/axvisor/configs/board/roc-rk3568-pc.toml
@ZR233 ZR233 closed this May 26, 2026

@mai-team-app mai-team-app Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR #943 Review — 文件系统栈重构(axfs-ng → axfs 统一)

总体评价:✅ Approve

这是一次非常高质量的大规模重构(205 文件,+3169/-8189),将 axfs-ng/axfs-ng-vfs 合并为统一的 axfs/axfs-vfs,架构清晰,文档详尽。


架构变更亮点

  1. 模块划分清晰block.rs(块设备抽象)、discovery.rs(卷发现与挂载)、highlevel/fs.rs(FsContext 全局状态)、highlevel/file.rs(文件抽象与页缓存)各司其职,职责边界明确。

  2. Mount 传播修复mount.rs):使用独立副本替代共享 Arc,解决了 bind mount 和 pivot_mount 时的传播语义问题,这是正确的设计。

  3. POSIX 语义改进

    • O_PATH 支持(不实际打开文件)
    • append 写入锁下沉到 inode 级别,避免多 fd 间的竞态
    • 正确处理尾随斜杠和空路径的 openat 语义
  4. ramfs rename 重写:从递归实现改为栈式迭代,避免内核栈溢出风险。

  5. FAT 时间转换:不再对无效日期 panic,改为静默降级。

  6. rsext4 拼写修正inodetable_cahceinodetable_cache

  7. 消除重复 crate:完全移除了 axfs-ng-vfs,统一为 axfs-vfs


本地验证结果

检查项 结果
cargo fmt --check ✅ 通过
clippy --package ax-fs-vfs ✅ 通过
clippy --package ax-fs-ramfs ✅ 通过
clippy --package ax-fs ✅ 通过(10/10)
clippy --package rsext4 ✅ 通过(2/2)
clippy --package ax-api ✅ 通过(13/13)

重叠分析

已扫描仓库全部 open PR,未发现与文件系统栈相关的重叠 PR。其他 open PR(#892 eBPF JIT、#961 RISC-V 动态平台等)均与本 PR 无关。


CI 状态

PR 已合并(2026-05-26)。CI 中 Release-plz release 的失败与本次代码变更无关(Release 自动化问题),其余 lint/format 检查通过或被跳过。


总结

一次非常出色的基础设施重构。代码质量高,PR 文档堪称范本(~5000 字的详细设计说明)。所有本地静态检查均通过,无阻塞问题。建议 approve。

Powered by glm-5.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants